#pragma once

#include "znx_rbtree.h"
#include "znx_queue.h"
#include "znx_cleanup.h"
#include "znx_thread_base.h"

#define ZNX_POOL_PAGE_SIZE              (1 << 12)   // 4K
#define ZNX_PAGE_MAX_ALLOC_SIZE         (1 << 9)    // 512B
#define ZNX_POOL_ALLOC_ALIGNED_SIZE     (8)


// manage memory space over MY_PAGE_MAX_ALLOC_SIZE size
typedef struct {
    znx_rbtree_node_t                   tree_node;
    void                                *ptr;
} znx_pool_block_node_t;


typedef struct {
    znx_queue_t                         queue;
    u_char                              *start;
    u_char                              *end;
    u_char                              *pos;
} znx_pool_page_t;


typedef struct {
    znx_queue_t                         pages;
    znx_pool_page_t                     *cur_page;
    znx_rbtree_t                        block_tree;
    znx_rbtree_node_t                   block_sentinel;
    znx_cleanup_list_t                  cleanup_list;
} znx_pool_t;


znx_pool_t *znx_pool_create();
void znx_pool_destroy(znx_pool_t *pool);

void *znx_pool_malloc(znx_pool_t *pool, size_t size);
void znx_pool_free(znx_pool_t *pool, void *ptr);

void *znx_pool_block_malloc(znx_pool_t *pool, size_t size);
void znx_pool_block_free(znx_pool_t *pool, void *ptr);

static inline void *
znx_pool_calloc(znx_pool_t *pool, size_t size)
{
    void *ptr = znx_pool_malloc(pool, size);
    bzero(ptr, size);
    return ptr;
}

static inline znx_cleanup_item_t *
znx_pool_add_cleanup(znx_pool_t *pool,
    znx_cleanup_handler_pt handler, void *ptr)
{
    return znx_cleanup_list_add(&pool->cleanup_list, handler, ptr);
}


static inline void
znx_pool_del_cleanup(znx_pool_t *pool, znx_cleanup_item_t *item)
{
    return znx_cleanup_list_del(&pool->cleanup_list, item);
}

